package main

import (
	"context"
	"fmt"
	"golang.org/x/sync/errgroup"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"
)

func main() {
	log.Println("第三周作业")

	g, ctx := errgroup.WithContext(context.Background())

	http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
		_, err := writer.Write([]byte("hello gopher"))
		if err != nil {
			log.Printf("write error: %v\n", err)
		}
	})

	serverOut := make(chan struct{})
	http.HandleFunc("/shutdown", func(writer http.ResponseWriter, request *http.Request) {
		serverOut <- struct{}{}
	})

	srv := &http.Server{
		Addr: ":8088",
		Handler: http.DefaultServeMux,
	}

	g.Go(func() error {
		// 当服务关闭的时候，这里会返回一个 error
		return srv.ListenAndServe()
	})

	g.Go(func() error {
		select {
		case <-ctx.Done():
			log.Printf("errgroup 退出了...; %v\n", ctx.Err())
		case <-serverOut:
			log.Println("通过指令关闭了服务...")
		}

		timeoutCtx, cancel := context.WithTimeout(context.Background(), 10 * time.Second)
		defer cancel()
		log.Println("服务正在关闭....")
		return srv.Shutdown(timeoutCtx)
	})

	g.Go(func() error {
		quitChan := make(chan os.Signal)
		signal.Notify(quitChan, syscall.SIGINT, syscall.SIGTERM)
		// log.Println("服务运行中 http://127.0.0.1:8088")
		select {
		case sig := <- quitChan:
			// 这里返回一个错误信息，让 errgroup 里面触发context的cancel
			return fmt.Errorf("get os signal: %v", sig)
		case <- ctx.Done():
			log.Println("服务已经关闭了...")
			return ctx.Err()
		}
		// timeoutCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		// defer cancel()
		// return srv.Shutdown(timeoutCtx)
	})

	log.Printf("等待 errgroup 结束 %v\n", g.Wait())
}
